﻿using System.Globalization;

namespace System
{
    /// <summary>
    /// Usefull extensions for Data Formatting based on Specific <see cref="CultureInfo">Culture</see>.
    /// </summary>
    public static class DataFormattingExtensions
    {
        private const string GeneralDateFormat = "{0:g}";
        private const string SimplePercentageFormat = "{0:0%}";
        private const string GeneralPercentageFormat = "{0:P}";
        private const string IntegerValueFormat = "{0:#,0}";
        private const string RealValueFormat = "{0:#,0.00}";

        /// <summary>
        /// Converts <see cref="DateTime">Date/Time value</see> to <see cref="CultureInfo">localized</see> general Date/Time presentation.
        /// </summary>
        /// <param name="value"><see cref="DateTime">Date/Time value</see>.</param>
        /// <param name="culture"><see cref="CultureInfo">Culture</see>.</param>
        /// <returns><see cref="CultureInfo">Localized</see> general Date/Time presentation.</returns>
        public static string ToCultureAwareGeneralDateTime(this DateTime? value, CultureInfo culture = null)
        {
            return !value.HasValue ? null : value.Value.ToCultureAwareGeneralDateTime(culture);
        }

        /// <summary>
        /// Converts <see cref="DateTime">Date/Time value</see> to <see cref="CultureInfo">localized</see> general Date/Time presentation.
        /// </summary>
        /// <param name="value"><see cref="DateTime">Date/Time value</see>.</param>
        /// <param name="culture"><see cref="CultureInfo">Culture</see>.</param>
        /// <returns><see cref="CultureInfo">Localized</see> general Date/Time presentation.</returns>
        public static string ToCultureAwareGeneralDateTime(this DateTime value, CultureInfo culture = null)
        {
            return String.Format(culture ?? CultureInfo.CurrentCulture, GeneralDateFormat, value);
        }

        /// <summary>
        /// Converts value to <see cref="CultureInfo">localized</see> simple percentage presentation.
        /// </summary>
        /// <param name="value"><see cref="DateTime">Value</see>.</param>
        /// <param name="culture"><see cref="CultureInfo">Culture</see>.</param>
        /// <returns><see cref="CultureInfo">Localized</see> simple percentage presentation.</returns>
        public static string ToCultureAwareIntegerPercentage(this double value, CultureInfo culture = null)
        {
            return String.Format(culture ?? CultureInfo.CurrentCulture, SimplePercentageFormat, value);
        }

        /// <summary>
        /// Converts value to <see cref="CultureInfo">localized</see> percentage presentation.
        /// </summary>
        /// <param name="value"><see cref="DateTime">Value</see>.</param>
        /// <param name="culture"><see cref="CultureInfo">Culture</see>.</param>
        /// <returns><see cref="CultureInfo">Localized</see> percentage presentation.</returns>
        public static string ToCultureAwarePercentage(this double value, CultureInfo culture = null)
        {
            return String.Format(culture ?? CultureInfo.CurrentCulture, GeneralPercentageFormat, value);
        }

        /// <summary>
        /// Converts value to <see cref="CultureInfo">localized</see> integer presentation.
        /// </summary>
        /// <param name="value"><see cref="DateTime">Value</see>.</param>
        /// <param name="culture"><see cref="CultureInfo">Culture</see>.</param>
        /// <returns><see cref="CultureInfo">Localized</see> integer presentation.</returns>
        public static string ToCultureAwareIntegerString(this long value, CultureInfo culture = null)
        {
            return String.Format(culture ?? CultureInfo.CurrentCulture, IntegerValueFormat, value);
        }

        /// <summary>
        /// Converts value to <see cref="CultureInfo">localized</see> real-value presentation.
        /// </summary>
        /// <param name="value"><see cref="DateTime">Value</see>.</param>
        /// <param name="culture"><see cref="CultureInfo">Culture</see>.</param>
        /// <returns><see cref="CultureInfo">Localized</see> real-value presentation.</returns>
        public static string ToCultureAwareRealString(this double value, CultureInfo culture = null)
        {
            return String.Format(culture ?? CultureInfo.CurrentCulture, RealValueFormat, value);
        }

        /// <summary>
        /// Converts value to <see cref="CultureInfo">localized</see> real-value presentation with sign (+/-).
        /// </summary>
        /// <param name="value"><see cref="DateTime">Value</see>.</param>
        /// <param name="culture"><see cref="CultureInfo">Culture</see>.</param>
        /// <returns><see cref="CultureInfo">Localized</see> real-value presentation with sign (+/-).</returns>
        public static string ToCultureAwareSignedRealString(this double value, CultureInfo culture = null)
        {
            var tmp = culture ?? CultureInfo.CurrentCulture;

            var val = value.ToCultureAwareRealString(tmp);

            return value > 0.0 ? String.Concat(tmp.NumberFormat.PositiveSign, val) : val;
        }

        /// <summary>
        /// Converts value to <see cref="CultureInfo">localized</see> integer presentation with sign (+/-).
        /// </summary>
        /// <param name="value"><see cref="DateTime">Value</see>.</param>
        /// <param name="culture"><see cref="CultureInfo">Culture</see>.</param>
        /// <returns><see cref="CultureInfo">Localized</see> integer presentation with sign (+/-).</returns>
        public static string ToCultureAwareSignedIntegerString(this long value, CultureInfo culture = null)
        {
            var tmp = culture ?? CultureInfo.CurrentCulture;

            var val = value.ToCultureAwareIntegerString(tmp);

            return value > 0 ? String.Concat(tmp.NumberFormat.PositiveSign, val) : val;
        }

        /// <summary>
        /// Converts value to <see cref="CultureInfo">localized</see> simple(integer) percentage presentation with sign (+/-).
        /// </summary>
        /// <param name="value"><see cref="DateTime">Value</see>.</param>
        /// <param name="culture"><see cref="CultureInfo">Culture</see>.</param>
        /// <returns><see cref="CultureInfo">Localized</see> simple(integer) percentage presentation with sign (+/-).</returns>
        public static string ToCultureAwareSignedSimplePercentageString(this double value, CultureInfo culture = null)
        {
            var tmp = culture ?? CultureInfo.CurrentCulture;

            var val = value.ToCultureAwareIntegerPercentage(tmp);

            return value > 0.0 ? String.Concat(tmp.NumberFormat.PositiveSign, val) : val;
        }

        /// <summary>
        /// Converts value to <see cref="CultureInfo">localized</see> percentage presentation with sign (+/-).
        /// </summary>
        /// <param name="value"><see cref="DateTime">Value</see>.</param>
        /// <param name="culture"><see cref="CultureInfo">Culture</see>.</param>
        /// <returns><see cref="CultureInfo">Localized</see> percentage presentation with sign (+/-).</returns>
        public static string ToCultureAwareSignedPercentageString(this double value, CultureInfo culture = null)
        {
            var tmp = culture ?? CultureInfo.CurrentCulture;

            var val = value.ToCultureAwarePercentage(tmp);

            return value > 0.0 ? String.Concat(tmp.NumberFormat.PositiveSign, val) : val;
        }
    }
}
